﻿#include <windows.h>
#include <winioctl.h>
#include <iostream>
#include <string>
#include <setupapi.h>
#include <cfgmgr32.h>
#include <fcntl.h>
#include <io.h>

#pragma comment(lib, "setupapi.lib")
#pragma comment(lib, "ole32.lib")

// 获取物理磁盘的友好名称
std::wstring GetDiskFriendlyName(const std::wstring& devicePath) {
    std::wstring friendlyName = L"未知";
    
    // 获取设备实例句柄
    HDEVINFO hDevInfo = SetupDiGetClassDevs(
        &GUID_DEVINTERFACE_DISK,
        NULL,
        NULL,
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
    );
    
    if (hDevInfo == INVALID_HANDLE_VALUE) {
        return friendlyName;
    }
    
    SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
    deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    
    // 枚举所有磁盘设备
    for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_DISK, i, &deviceInterfaceData); i++) {
        DWORD requiredSize = 0;
        
        // 获取设备接口详细信息所需的大小
        SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, NULL, 0, &requiredSize, NULL);
        
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
            continue;
        }
        
        PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = 
            (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);
        deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
        
        SP_DEVINFO_DATA devInfoData;
        devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
        
        if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, 
                                           deviceInterfaceDetailData, requiredSize, 
                                           NULL, &devInfoData)) {
            
            // 检查是否是我们正在查找的设备
            if (wcscmp(deviceInterfaceDetailData->DevicePath, devicePath.c_str()) == 0) {
                // 获取友好名称
                WCHAR buffer[256];
                DWORD bufferSize = sizeof(buffer);
                
                if (SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfoData,
                                                    SPDRP_FRIENDLYNAME,
                                                    NULL, (PBYTE)buffer, bufferSize, NULL)) {
                    friendlyName = buffer;
                }
                break;
            }
        }
        
        free(deviceInterfaceDetailData);
    }
    
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return friendlyName;
}

std::wstring GetDiskFriendlyName(UINT driveNumber) {
    std::wstring friendlyName = L"未知";
    
    HDEVINFO hDevInfo = SetupDiGetClassDevs(
        &GUID_DEVINTERFACE_DISK,
        NULL,
        NULL,
        DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
    );
    
    if (hDevInfo == INVALID_HANDLE_VALUE)
    {

        std::wcout << L"打开磁盘失败" << std::endl;
        return friendlyName;
    } 
    
    SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { sizeof(SP_DEVICE_INTERFACE_DATA) };
    
    for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_DISK, i, &deviceInterfaceData); i++) {
        DWORD requiredSize = 0;
        SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, NULL, 0, &requiredSize, NULL);
        
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) continue;
        
        auto deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiredSize);
        deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
        
        SP_DEVINFO_DATA devInfoData = { sizeof(SP_DEVINFO_DATA) };
        
        if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, 
                                           deviceInterfaceDetailData, requiredSize, NULL, &devInfoData)) {
            // 检查设备路径是否包含 PhysicalDriveX
            if (wcsstr(deviceInterfaceDetailData->DevicePath, (L"PhysicalDrive" + std::to_wstring(driveNumber)).c_str())) {
                WCHAR buffer[256];
                if (SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_FRIENDLYNAME,
                                                    NULL, (PBYTE)buffer, sizeof(buffer), NULL)) {
                    friendlyName = buffer;
                }
                break;
            }
        }
        free(deviceInterfaceDetailData);
    }
    
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return friendlyName;
}
// 获取物理磁盘的详细信息
bool GetPhysicalDiskInfo() {
    std::wstring physicalDrivePath = L"\\\\.\\PhysicalDrive1";
    
    HANDLE hDevice = CreateFile(
        physicalDrivePath.c_str(),  // 第一物理磁盘
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL
    );

    if (hDevice == INVALID_HANDLE_VALUE) {
        std::wcout << L"无法打开物理磁盘。错误代码: " << GetLastError() << std::endl;
        return false;
    }

    // 获取友好名称
    std::wstring friendlyName = GetDiskFriendlyName(1);
    std::wcout << L"=== 磁盘基本信息 ===" << std::endl;
    std::wcout << L"设备路径: " << physicalDrivePath << std::endl;
    std::wcout << L"友好名称: " << friendlyName << std::endl;

    // 获取磁盘几何信息
    DISK_GEOMETRY diskGeometry;
    DWORD bytesReturned;
    
    if (DeviceIoControl(
        hDevice,
        IOCTL_DISK_GET_DRIVE_GEOMETRY,
        NULL,
        0,
        &diskGeometry,
        sizeof(diskGeometry),
        &bytesReturned,
        NULL
    )) {
        std::wcout << L"\n=== 磁盘几何信息 ===" << std::endl;
        std::wcout << L"柱面数: " << diskGeometry.Cylinders.QuadPart << std::endl;
        
        // 磁盘类型转换
        std::wstring mediaType;
        switch (diskGeometry.MediaType) {
            case FixedMedia: mediaType = L"固定硬盘"; break;
            case RemovableMedia: mediaType = L"可移动媒体"; break;
            case F3_1Pt44_512: mediaType = L"3.5\" 1.44MB"; break;
            case F3_2Pt88_512: mediaType = L"3.5\" 2.88MB"; break;
            case F5_1Pt2_512: mediaType = L"5.25\" 1.2MB"; break;
            case F5_360_512: mediaType = L"5.25\" 360KB"; break;
            case F3_720_512: mediaType = L"3.5\" 720KB"; break;
            case F3_20Pt8_512: mediaType = L"3.5\" 20.8MB"; break;
            case F3_120M_512: mediaType = L"3.5\" 120MB"; break;
            case F3_128Mb_512: mediaType = L"3.5\" 128MB"; break;
            case F3_230Mb_512: mediaType = L"3.5\" 230MB"; break;
            case F8_256_128: mediaType = L"8\" 256KB"; break;
            default: mediaType = L"未知类型"; break;
        }
        std::wcout << L"磁盘类型: " << mediaType << std::endl;
        
        std::wcout << L"每磁道扇区数: " << diskGeometry.SectorsPerTrack << std::endl;
        std::wcout << L"每柱面磁道数: " << diskGeometry.TracksPerCylinder << std::endl;
        std::wcout << L"字节每扇区: " << diskGeometry.BytesPerSector << std::endl;
        
        // 计算总容量
        ULONGLONG totalSize = diskGeometry.Cylinders.QuadPart *
                             diskGeometry.TracksPerCylinder *
                             diskGeometry.SectorsPerTrack *
                             diskGeometry.BytesPerSector;
        
        std::wcout << L"总容量: " << totalSize / (1024 * 1024 * 1024) << L" GB" << std::endl;
        std::wcout << L"总字节数: " << totalSize << L" 字节" << std::endl;
    } else {
        std::wcout << L"获取磁盘几何信息失败。错误代码: " << GetLastError() << std::endl;
    }

    // 获取分区信息
    DRIVE_LAYOUT_INFORMATION_EX* layoutInfo = NULL;
    DWORD bufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + sizeof(PARTITION_INFORMATION_EX) * 128;
    layoutInfo = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(bufferSize);

    if (DeviceIoControl(
        hDevice,
        IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
        NULL,
        0,
        layoutInfo,
        bufferSize,
        &bytesReturned,
        NULL
    )) {
        std::wcout << L"\n=== 分区信息 ===" << std::endl;
        
        // 分区表类型
        std::wstring partitionStyle;
        switch (layoutInfo->PartitionStyle) {
            case PARTITION_STYLE_MBR: partitionStyle = L"MBR"; break;
            case PARTITION_STYLE_GPT: partitionStyle = L"GPT"; break;
            case PARTITION_STYLE_RAW: partitionStyle = L"RAW"; break;
            default: partitionStyle = L"未知"; break;
        }
        std::wcout << L"分区表类型: " << partitionStyle << std::endl;
        std::wcout << L"分区数量: " << layoutInfo->PartitionCount << std::endl;

        for (DWORD i = 0; i < layoutInfo->PartitionCount; i++) {
            PARTITION_INFORMATION_EX& part = layoutInfo->PartitionEntry[i];
            if (part.PartitionNumber > 0) {  // 有效的分区
                std::wcout << L"\n分区 " << part.PartitionNumber << L":" << std::endl;
                std::wcout << L"  起始偏移: " << part.StartingOffset.QuadPart << L" 字节" << std::endl;
                std::wcout << L"  分区长度: " << part.PartitionLength.QuadPart / (1024 * 1024) << L" MB" << std::endl;
                
                std::wstring partStyle;
                switch (part.PartitionStyle) {
                    case PARTITION_STYLE_MBR: 
                        partStyle = L"MBR";
                        std::wcout << L"  分区类型: MBR (0x" << std::hex << part.Mbr.PartitionType << std::dec << L")" << std::endl;
                        if (part.Mbr.BootIndicator) {
                            std::wcout << L"  可启动分区: 是" << std::endl;
                        }
                        break;
                    case PARTITION_STYLE_GPT: 
                        partStyle = L"GPT";
                        std::wcout << L"  分区类型: GPT" << std::endl;
                        WCHAR guidStr[40];
                        StringFromGUID2(part.Gpt.PartitionType, guidStr, 40);
                        std::wcout << L"  分区GUID类型: " << guidStr << std::endl;
                        StringFromGUID2(part.Gpt.PartitionId, guidStr, 40);
                        std::wcout << L"  分区GUID: " << guidStr << std::endl;
                        std::wcout << L"  属性: " << part.Gpt.Attributes << std::endl;
                        std::wcout << L"  名称: " << part.Gpt.Name << std::endl;
                        break;
                    case PARTITION_STYLE_RAW: partStyle = L"RAW"; break;
                    default: partStyle = L"未知"; break;
                }
                std::wcout << L"  分区样式: " << partStyle << std::endl;
            }
        }
    } else {
        std::wcout << L"获取分区信息失败。错误代码: " << GetLastError() << std::endl;
    }

    // 获取磁盘缓存信息
    DISK_CACHE_INFORMATION cacheInfo;
    if (DeviceIoControl(
        hDevice,
        IOCTL_DISK_GET_CACHE_INFORMATION,
        NULL,
        0,
        &cacheInfo,
        sizeof(cacheInfo),
        &bytesReturned,
        NULL
    )) {
        std::wcout << L"\n=== 磁盘缓存信息 ===" << std::endl;
        std::wcout << L"参数可保存: " << (cacheInfo.ParametersSavable ? L"是" : L"否") << std::endl;
        std::wcout << L"读缓存启用: " << (cacheInfo.ReadCacheEnabled ? L"是" : L"否") << std::endl;
        std::wcout << L"写缓存启用: " << (cacheInfo.WriteCacheEnabled ? L"是" : L"否") << std::endl;
        std::wcout << L"预读启用: " << (cacheInfo.PrefetchScalar ? L"是" : L"否") << std::endl;
    }

    free(layoutInfo);
    CloseHandle(hDevice);
    return true;
}

int main2() {
    _setmode(_fileno(stdout), _O_U16TEXT);
    
    std::wcout << L"获取第一物理磁盘信息..." << std::endl;
    
    if (!GetPhysicalDiskInfo()) {
        std::wcout << L"获取磁盘信息失败!" << std::endl;
        return 1;
    }
    
    std::wcout << L"\n操作完成!" << std::endl;
    system("pause");
    return 0;
}
int main() {
    _setmode(_fileno(stdout), _O_U16TEXT);
    
    auto res = GetDiskFriendlyName(0);
    std::wcout << res << std::endl;

    return 0;
}